-
Notifications
You must be signed in to change notification settings - Fork 97
smartcontract: add support for NEP-25 #4036
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## master #4036 +/- ##
==========================================
+ Coverage 72.48% 74.49% +2.01%
==========================================
Files 364 365 +1
Lines 56750 47958 -8792
==========================================
- Hits 41135 35727 -5408
+ Misses 13880 10490 -3390
- Partials 1735 1741 +6 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
roman-khimov
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- semantic checks
- stack item serialization
See neo-project/neo#4043 also
| Overloads map[string]string `yaml:"overloads,omitempty"` | ||
| NamedTypes map[string]binding.ExtendedType `yaml:"namedtypes,omitempty"` | ||
| Overloads map[string]string `yaml:"overloads,omitempty"` | ||
| NamedTypes map[string]manifest.ExtendedType `yaml:"namedtypes,omitempty"` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Likely it's no longer needed here, manifest has it all.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do I need to write an UnmarshalYAML method for ProjectConfig or mark the NamedTypes field as deprecated?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just drop them and then let's see how it goes.
|
|
||
| import ( | ||
| "encoding/json" | ||
| "gopkg.in/yaml.v3" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Likely we no longer need yaml here.
0457d1a to
a8966da
Compare
AnnaShaleva
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please, adjust the PR/commit description, it points to the wrong issue.
a8966da to
2ffd0fd
Compare
AnnaShaleva
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please, check the compatibility with the reference implementation, especially in the part of extended type verification and circular references.
| extendedtype: | ||
| base: Struct | ||
| name: crazyStruct | ||
| fields: | ||
| - field: I | ||
| base: Integer | ||
| - field: B | ||
| base: Boolean |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do you include fields in the definition of named extended type? It shouldn't be like that, all named types should be specified in the namedtypes section, and extended type here should just point to a specific named type.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We no longer store namedtypes in the config, so I don't quite understand where the author should specify the definition of named type.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We no longer store namedtypes in the config
They still should be presented in a separate section of config file, like it's done for manifest (https://github.com/neo-project/proposals/blob/master/nep-25.mediawiki#contract). Otherwise, we have to declare named type in-place every time it's used in the contract config. Consider the same named type used in multiple events, for example.
This namedtypes section of config will be relevant for events only and will likely be removed once we solve #3027. Until this issue is solved, namedtypes section is the only place that can be used for manifest's events construction.
@roman-khimov, I need your opinion here because it was your request (https://github.com/nspcc-dev/neo-go/pull/4036/files#r2419192068). So far, we used config-based events for type casting at the compiler level and to compare the emitted event types with the desired ones. If we still want to support this feature, then we need namedtypes section to be resented in the contract config. ACK?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, keeping them isn't hard. I've not seen code throwing structures in events (other than examples), but #3027 seems to be the key here.
| if err := node.Decode(&raw); err != nil { | ||
| return err | ||
| } | ||
| if v, ok := raw["base"]; ok { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From what I understand, there shouldn't be base field.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
JSON format should be compatible with C#.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought I needed to support the old format, but I don't need to do that, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right. No old format support, we'll migrate to the NEP-25 without transition period.
| if e.Base != smartcontract.InteropInterfaceType { | ||
| return fmt.Errorf("`ExtendedType.Interface` field can not be specified for %s", e.Base) | ||
| } | ||
| if e.Interface != "IIterator" { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There should be a constant for IIterator in our codebase.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I found the constant only here
neo-go/pkg/neorpc/result/invoke.go
Line 48 in 2ffd0fd
| const iteratorInterfaceName = "IIterator" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Make it exported, move to a suitable package and reuse.
| } | ||
| e.Fields[i] = p | ||
| } | ||
| return nil |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should heck if the resulting type (and all nested ones) are valid.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should we call the Valid() method? why don't we do this for, for example, manifest.Parameter?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should we call the Valid() method?
Yes. Check the reference implementation for that.
why don't we do this for, for example, manifest.Parameter?
Check how it's handled in the reference implementation and attach the link to the discussion.
Close #3595. Signed-off-by: Tural Devrishev <[email protected]>
2ffd0fd to
8cccd96
Compare
| extendedtype: | ||
| base: Struct | ||
| name: crazyStruct | ||
| fields: | ||
| - field: I | ||
| base: Integer | ||
| - field: B | ||
| base: Boolean |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We no longer store namedtypes in the config
They still should be presented in a separate section of config file, like it's done for manifest (https://github.com/neo-project/proposals/blob/master/nep-25.mediawiki#contract). Otherwise, we have to declare named type in-place every time it's used in the contract config. Consider the same named type used in multiple events, for example.
This namedtypes section of config will be relevant for events only and will likely be removed once we solve #3027. Until this issue is solved, namedtypes section is the only place that can be used for manifest's events construction.
@roman-khimov, I need your opinion here because it was your request (https://github.com/nspcc-dev/neo-go/pull/4036/files#r2419192068). So far, we used config-based events for type casting at the compiler level and to compare the emitted event types with the desired ones. If we still want to support this feature, then we need namedtypes section to be resented in the contract config. ACK?
| name := "unnamed" | ||
| if c.buildInfo.options.CollectedNamedTypes != nil { | ||
| for c.buildInfo.options.CollectedNamedTypes[name].Name == name { | ||
| name = name + "X" | ||
| } | ||
| _ = c.genStructExtended(typ, name, c.buildInfo.options.CollectedNamedTypes) | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Duplicating code.
| return | ||
| } | ||
| var ( | ||
| seen = make(map[types.Type]bool) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
map[types.Type]struct{}
| // GuessEventTypes specifies if types of runtime notifications need to be guessed | ||
| // from the usage context. These types are used for RPC binding generation only and | ||
| // GuessedNamedTypes specifies guessed from the usage context named types of | ||
| // runtime notifications. These types are used for RPC binding generation only and |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a note that it's nil in case if ...
| // can be defined for events with name known at the compilation time and without | ||
| // variadic args usages. If some type is specified via config file, then the config's | ||
| // one is preferable. Currently, event's parameter type is defined from the first | ||
| // variadic args usages. Currently, event's parameter type is defined from the first |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changes regarding config file may be reverted after the resolution of https://github.com/nspcc-dev/neo-go/pull/4036/files#r2511308314.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just don't forget we have two configs currently, contract-level and bindings-level, contract one stays in some form anyway, but bindings only need a manifest.
| pa := &e.Fields[i] | ||
| pb := &other.Fields[i] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a and b.
| if err := node.Decode(&raw); err != nil { | ||
| return err | ||
| } | ||
| if v, ok := raw["base"]; ok { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right. No old format support, we'll migrate to the NEP-25 without transition period.
| } | ||
| e.Fields[i] = p | ||
| } | ||
| return nil |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should we call the Valid() method?
Yes. Check the reference implementation for that.
why don't we do this for, for example, manifest.Parameter?
Check how it's handled in the reference implementation and attach the link to the discussion.
| if !unicode.IsLetter(rune(e.Name[0])) { | ||
| return errors.New("`ExtendedType.Name` must start with a letter") | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we use regexp, then this logic should be a part of regexp. Check the reference implementation.
| if e.Base != smartcontract.InteropInterfaceType { | ||
| return fmt.Errorf("`ExtendedType.Interface` field can not be specified for %s", e.Base) | ||
| } | ||
| if e.Interface != "IIterator" { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Make it exported, move to a suitable package and reuse.
|
We also need to port Faun-related logic, ref. https://github.com/neo-project/neo/pull/4283/files#diff-56a96400470d169fb83598d289f068d661f906f74e2432ea3685988611331f12R193-R196 |
| alphaNumDot = regexp.MustCompile(`^[A-Za-z0-9.]+$`) | ||
| ) | ||
|
|
||
| type ExtendedType struct { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Exported type needs comment.
Close #3595.